#include <math.h>
#include <iostream>
#include <set>

using std::cout;
using std::endl;
using std::set;

class Point
{
public:
    Point(int x,int y)
        :_x(x)
         ,_y(y)
    {

    }

    ~Point()
    {

    }

    double getDistance()const 
    {
        return sqrt(pow(_x,2)+pow(_y,2));
    }
    int getx()const
    {
        return _x;
    }
    int gety()const 
    {
        return _y;
    }

    friend std::ostream &operator<<(std::ostream &os,const Point &rhs);
    friend bool operator<(const Point &lhs,const Point &rhs);
    friend struct ComparePoint;
private:
    int _x;
    int _y;
};

#if 0
    template <typename Container>
void display(const Container &con)
{
    for(auto &ele:con)
    {
        cout << ele << " ";
    }
    cout << endl;
}

std::ostream &operator<<(std::ostream &os,const Point &rhs)
{
    os << "(" << rhs._x
        << "," << rhs._y
        << ")";
    return os;
}
#endif 

    template <typename Container>
void display(const Container &con)
{
    for(auto &ele:con)
    {
        cout << "(" << ele.getx()
            << "," << ele.gety()
            << ")" << "  ";
    }
    cout << endl;
}

bool operator<(const Point &lhs,const Point &rhs)
{
    if(lhs.getDistance() < rhs.getDistance())
    {
        return true;
    }
    else if(lhs.getDistance() == rhs.getDistance())
    {
        if(lhs.getx() < rhs.getx())
        {
            return true;
        }
        else if(lhs.getx() == rhs.getx())
        {
            if(lhs.gety() < rhs.gety())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

struct ComparePoint
{
    bool operator()(const Point &lhs,const Point &rhs)const 
    {
        cout << "struct ComparePoint" << endl;
        if(lhs.getDistance() < rhs.getDistance())
        {
            return true;
        }
        else if(lhs.getDistance() == rhs.getDistance())
        {
            if(lhs.getx() < rhs.getx())
            {
                return true;
            }
            else if(lhs.getx() == rhs.getx())
            {
                if(lhs.gety() < rhs.gety())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

};

namespace std
{
template <>
    struct less<Point>
{
    bool operator()(const Point &lhs,const Point &rhs)const
    {
        cout << "template <> struct std::less" << endl;
        if(lhs.getDistance() < rhs.getDistance())
        {
            return true;
        }
        else if(lhs.getDistance() == rhs.getDistance())
        {
            if(lhs.getx() < rhs.getx())
            {
                return true;
            }
            else if(lhs.getx() == rhs.getx())
            {
                if(lhs.gety() < rhs.gety())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

};
}// end of 



void test(){
    set<Point> number = {
    /* set<Point, ComparePoint> number = { */
        Point(1, 2),
        Point(3, 2),
        Point(-1, 2),
        Point(-2, 2),
        Point(1, 2),
        Point(1, -2),
    };
    display(number);
}

int main()
{
    test();
    return 0;
}
